﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using GSSoftSL.Utility;
using GSSoftSL.Web.Models;
using GSSoftSL.Web.Services;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Newtonsoft.Json;

namespace GSSoftSL.ViewModel
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm/getstarted
    /// </para>
    /// </summary>
    public class DiemSoViewModel : ViewModelBase
    {
        private Action _setGridColumnPropertyCallBack;
        public Action SetGridColumnPropertyCallBack
        {
            get { return _setGridColumnPropertyCallBack; }
            set { _setGridColumnPropertyCallBack = value; }
        }
        

        private GSSoftContext _dc;
        public GSSoftContext DC
        {
            get { return _dc; }
        }

        /// <summary>
        /// Initializes a new instance of the DiemSoViewModel class.
        /// </summary>
        public DiemSoViewModel()
        {
            Init();
        }

        private void Init()
        {
            CotDiemInfo.CallBack = LoadDiemSoData;
            _dc = new GSSoftContext();//(GSSoftContext) context;
            IsBusy = true;
            _dc.Load(_dc.GetMonsQuery().OrderBy(n => n.ThuTu), LoadBehavior.RefreshCurrent, LoadMon_Completed, null);
        }

        private void LoadMon_Completed(LoadOperation<Mon> load)
        {
            var lstMons = load.Entities.ToList();
            lstMons.Insert(0, new Mon(){MaMon = "-1", TenMon = "- Chọn môn -"});
            Mons = lstMons.ToArray();
            IsBusy = false;
        }

        #region Bindable Properties

        /*private DiemSoDataGridVM _diemSoDataGrid = new DiemSoDataGridVM();
        public DiemSoDataGridVM DiemSoDataGrid
        {
            get { return _diemSoDataGrid; }
        }*/
        

        private bool _isBusy = false;
        public bool IsBusy
        {
            get
            {
                return _isBusy;
            }
            set
            {
                if (_isBusy == value)
                {
                    return;
                }
                _isBusy = value;
                RaisePropertyChanged("IsBusy");
            }
        }
        
        private Mon[] _mons = null;
        public Mon[] Mons
        {
            get
            {
                return _mons;
            }
            set
            {
                if (_mons == value)
                {
                    return;
                }
                _mons = value;
                RaisePropertyChanged("Mons");
                if (_mons != null && _mons.Length > 0)
                    Mon = _mons.First();
                else
                    Mon = null;
            }
        }
        
        private Mon _mon = null;
        public Mon Mon
        {
            get
            {
                return _mon;
            }
            set
            {
                if (_mon == value)
                {
                    return;
                }
                _mon = value;
                RaisePropertyChanged("Mon");
                if (_mon == null || _mon.MaMon == "-1")
                    Lops = null;
                else
                {
                    IsBusy = true;
                    _dc.Load(_dc.GetLopsQuery().Where(n => n.MaMon == _mon.MaMon).OrderBy(n => n.TenLop), LoadBehavior.RefreshCurrent, LoadLop_Completed,
                             null);
                }
            }
        }

        private void LoadLop_Completed(LoadOperation<Lop> load)
        {
            var lstLops = load.Entities.ToList();
            lstLops.Insert(0, new Lop(){MaLop = "-1", TenLop = "- Chọn lớp -"});
            Lops = lstLops.ToArray();
            IsBusy = false;
        }
        
        private Lop[] _lops = null;
        public Lop[] Lops
        {
            get
            {
                return _lops;
            }
            set
            {
                if (_lops == value)
                {
                    return;
                }
                _lops = value;
                RaisePropertyChanged("Lops");
                if (_lops != null && _lops.Length > 0)
                    Lop = _lops.First();
                else
                    Lop = null;
            }
        }
        
        private Lop _lop = null;
        public Lop Lop
        {
            get
            {
                return _lop;
            }
            set
            {
                if (_lop == value)
                {
                    return;
                }
                _lop = value;
                RaisePropertyChanged("Lop");
                if (_lop != null && _lop.MaLop != "-1")
                {
                    IsBusy = true;
                    /*_dc.Load(_dc.GetKhoaHocCotDiemsQuery().Where(n => n.KhoaHocId == _khoaHoc.KhoaHocId), LoadBehavior.RefreshCurrent,
                             LoadKhoaHocCotDiem_Completed, null);*/
                    _dc.Load(_dc.GetKhoaHocsQuery().Where(n => n.LopId == _lop.LopId), LoadBehavior.RefreshCurrent,
                             LoadKhoaHoc_Completed, null);
                }
                else
                {
                    KhoaHocs = null;
                }
            }
        }

        private void LoadKhoaHoc_Completed(LoadOperation<KhoaHoc> load)
        {
            var lstKhoaHocs = load.Entities.ToList();
            lstKhoaHocs.Insert(0, new KhoaHoc(){MaKhoaHoc = "-1", TenKhoaHoc = "- Chọn khóa học -"});
            KhoaHocs = lstKhoaHocs.ToArray();
            IsBusy = false;
        }

        private KhoaHoc[] _khoaHocs = null;
        public KhoaHoc[] KhoaHocs
        {
            get
            {
                return _khoaHocs;
            }
            set
            {
                if (_khoaHocs == value)
                {
                    return;
                }
                _khoaHocs = value;
                RaisePropertyChanged("KhoaHocs");
                if (_khoaHocs != null && _khoaHocs.Length > 0)
                {
                    KhoaHoc = _khoaHocs.First();
                }
                else
                {
                    KhoaHoc = null;
                }
            }
        }

        private KhoaHoc _khoaHoc = null;
        public KhoaHoc KhoaHoc
        {
            get
            {
                return _khoaHoc;
            }
            set
            {
                if (_khoaHoc == value)
                {
                    return;
                }
                _khoaHoc = value;
                RaisePropertyChanged("KhoaHoc");
                if (_khoaHoc != null && _khoaHoc.MaKhoaHoc != "-1")
                {
                    IsBusy = true;
                    _dc.Load(_dc.GetKhoaHocCotDiemsQuery().Where(n => n.KhoaHocId == _khoaHoc.KhoaHocId), LoadBehavior.RefreshCurrent,
                             LoadKhoaHocCotDiem_Completed, null);
                }
                else
                {
                    CotDiems = null;
                    HocVienDiems = null;
                    SetGridColumnPropertyCallBack();
                }
            }
        }

        private void LoadKhoaHocCotDiem_Completed(LoadOperation<KhoaHocCotDiem> load)
        {
            IsBusy = false;
            CotDiems =
                new ObservableCollection<CotDiemInfo>(load.Entities.Select(n => new CotDiemInfo()
                                                                                    {
                                                                                        STT = n.STT,
                                                                                        TenCot = n.Ten,
                                                                                        NgayKiemTra = n.NgayKiemTra,
                                                                                        IsSelected = false,
                                                                                        KhoaHocCotDiem = n,
                                                                                        KhoaHocId = n.KhoaHocId
                                                                                    }).ToArray());
        }

        private ObservableCollection<CotDiemInfo> _cotDiems = null;
        public ObservableCollection<CotDiemInfo> CotDiems
        {
            get
            {
                return _cotDiems;
            }
            set
            {
                if (_cotDiems == value)
                {
                    return;
                }
                _cotDiems = value;
                RaisePropertyChanged("CotDiems");
            }
        }
        
        private CotDiemInfo _cotDiemInfo = null;
        public CotDiemInfo CotDiemInfo
        {
            get
            {
                return _cotDiemInfo;
            }
            set
            {
                if (_cotDiemInfo == value)
                {
                    return;
                }
                _cotDiemInfo = value;
                RaisePropertyChanged("CotDiemInfo");
            }
        }
        
        private ObservableCollection<HocVienDiem> _hocVienDiems = null;
        public ObservableCollection<HocVienDiem> HocVienDiems
        {
            get
            {
                return _hocVienDiems;
            }
            set
            {
                if (_hocVienDiems == value)
                {
                    return;
                }
                _hocVienDiems = value;
                RaisePropertyChanged("HocVienDiems");
            }
        }

        #endregion

        #region Command

        private RelayCommand _loadCommand;
        public RelayCommand LoadCommand
        {
            get
            {
                return _loadCommand
                    ?? (_loadCommand = new RelayCommand(
                                          () =>
                                          {
                                              
                                          }));
            }
        }

        public void LoadDiemSoData()
        {
            /*_dc.Load(_dc.GetJsonDiemsByLopCots(Lop.LopId, CotDiems.Where(n => n.IsSelected).Select(n => n.STT).ToArray(),
                                               LoadDiemSo_Completed, null));*/
            if (CotDiems.Where(n => n.IsSelected).Count() == 0)
            {
                if (SetGridColumnPropertyCallBack != null)
                    SetGridColumnPropertyCallBack();
                return;
            }
            IsBusy = true;
            _dc.GetJsonDiemsByKhoaHocCots(_khoaHoc.KhoaHocId, CotDiems.Where(n => n.IsSelected).Select(n => n.STT).ToArray(),
                                          LoadDiemSo_Completed, null);
            //_dc.InvokeOperation()
        }

        private void LoadDiemSo_Completed(InvokeOperation<string> operation)
        {
            IsBusy = false;
            string json = operation.Value;
            DiemSo diem = JsonConvert.DeserializeObject<DiemSo>(json);
            HocVienDiems = new ObservableCollection<HocVienDiem>(diem.Diems);
            if (SetGridColumnPropertyCallBack != null)
                SetGridColumnPropertyCallBack();
        }

        private RelayCommand _addCotDiemCommand;
        public RelayCommand AddCotDiemCommand
        {
            get
            {
                return _addCotDiemCommand
                       ?? (_addCotDiemCommand = new RelayCommand(
                                                    () =>
                                                        {
                                                            if (Lop == null || KhoaHoc ==null)
                                                                return;
                                                            IsBusy = true;
                                                            KhoaHocCotDiem lcd = new KhoaHocCotDiem()
                                                                                 {
                                                                                     //STT = CotDiemInfo.STT,
                                                                                     Ten = CotDiemInfo.TenCot,
                                                                                     //LopId = Lop.LopId,
                                                                                     KhoaHocId = _khoaHoc.KhoaHocId,
                                                                                     NgayKiemTra = CotDiemInfo.NgayKiemTra,
                                                                                     NguoiTao =
                                                                                         UtilityFunction.
                                                                                         GetCurrentUserId(),
                                                                                     NgayTao = DateTime.Now
                                                                                 };
                                                            KhoaHoc.KhoaHocCotDiems.Add(lcd);
                                                            //_dc.KhoaHocCotDiems.Add(lcd);
                                                            _dc.SubmitChanges(AddCotDiem_Completed, lcd);
                                                        }));
            }
        }

        private void AddCotDiem_Completed(SubmitOperation operation)
        {
            IsBusy = false;
            if (!operation.HasError)
            {
                KhoaHocCotDiem lcd = operation.UserState as KhoaHocCotDiem;
                CotDiems.Add(new CotDiemInfo()
                                 {
                                     STT = lcd.STT,
                                     TenCot = lcd.Ten,
                                     NgayKiemTra = lcd.NgayKiemTra,
                                     KhoaHocId = lcd.KhoaHocId,
                                     KhoaHocCotDiem = lcd
                                 });
                RaisePropertyChanged("CotDiems");
            }
            else
            {
                MessageWindow.CreateNew("Lưu không thành công!");
            }
        }

        private RelayCommand _updateCotDiemCommand;
        public RelayCommand UpdateCotDiemCommand
        {
            get
            {
                return _updateCotDiemCommand
                    ?? (_updateCotDiemCommand = new RelayCommand(
                                          () =>
                                          {
                                              if (Lop == null || KhoaHoc == null || CotDiemInfo == null ||
                                                  CotDiemInfo.KhoaHocCotDiem == null)
                                                  return;

                                              CotDiemInfo.KhoaHocCotDiem.Ten = CotDiemInfo.TenCot;
                                              CotDiemInfo.KhoaHocCotDiem.KhoaHocId = _khoaHoc.KhoaHocId;
                                              CotDiemInfo.KhoaHocCotDiem.NgayKiemTra = CotDiemInfo.NgayKiemTra;
                                              if (_dc.HasChanges)
                                              {
                                                  IsBusy = true;
                                                  _dc.SubmitChanges(UpdateCotDiem_Completed, null);
                                              }
                                          }));
            }
        }

        private void UpdateCotDiem_Completed(SubmitOperation operation)
        {
            IsBusy = false;
            if (operation.HasError)
            {
                CotDiemInfo.TenCot = CotDiemInfo.KhoaHocCotDiem.Ten;
                CotDiemInfo.NgayKiemTra = CotDiemInfo.KhoaHocCotDiem.NgayKiemTra;
                _dc.RejectChanges();
                MessageWindow.CreateNew("Lưu không thành công!");
            }
        }

        private RelayCommand _loadDiemSoCommand;
        public RelayCommand LoadDiemSoCommand
        {
            get
            {
                return _loadDiemSoCommand
                    ?? (_loadDiemSoCommand = new RelayCommand(
                                          () =>
                                          {
                                              
                                          }));
            }
        }

        private RelayCommand _saveCommand;
        public RelayCommand SaveCommand
        {
            get
            {
                return _saveCommand
                    ?? (_saveCommand = new RelayCommand(
                                          () =>
                                              {
                                                  if (Lop == null || Mon == null || KhoaHoc == null || CotDiems.Where(n => n.IsSelected).Count() == 0)
                                                      return;
                                                  ConfirmWindow.CreateNew("Bạn có muốn lưu?", Save);
                                              }));
            }
        }

        private void Save()
        {
            IsBusy = true;
            DiemSo ds = new DiemSo();
            ds.KhoaHocId = KhoaHoc.KhoaHocId;
            ds.Cots = CotDiems.Where(n => n.IsSelected).Select(n => n.STT).ToArray();
            List<string> strCots = new List<string>();
            strCots.Add("MaHV");
            strCots.AddRange(ds.Cots.Select(n => "Cot" + n));
            ds.Diems = new List<HocVienDiem>(HocVienDiems);
            string json = JsonConvert.SerializeObject(ds, new JsonSerializerSettings
            {
                ContractResolver = new DiemSoContractResolver(strCots.ToArray())
            });
            _dc.SaveDiemSo(json, Save_Completed, null);
        }

        private void Save_Completed(InvokeOperation operation)
        {
            IsBusy = false;
            if(operation.HasError)
                MessageWindow.CreateNew("Lưu không thành công.");
        }

        #region Command Method
        #endregion

        #endregion

        
    }
}